package com.ruoyi.web.controller.project.excel;

import lombok.Data;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Data
public class ZlCell {
    /**
     * 单元格ID
     */
    private String cellNo;

    private int cellIndex;

    /**
     * 行
     */
    private ZlRow row;
    //单元格格式
    private CellStyle style;
    //单元格
    private Cell cell ;
    //工作簿
    private XSSFWorkbook wb;

    private ZlSheet sheet;

    /**
     * 字体
     */
    private Font font;

    private Object content;

    /**
     * 背景色
     */
    private IndexedColors background;

    /**
     * 字体颜色
     */
    private IndexedColors fontColor;

    private BorderStyle borderTop;

    private BorderStyle borderLeft;

    private BorderStyle borderBottom;

    private BorderStyle borderRight;

    public ZlCell(XSSFWorkbook wb,ZlSheet sheet,ZlRow row,Integer index,int width,String url){
        this.wb = wb;
        this.sheet = sheet;
        this.row = row;
        this.cell = row.getRow().createCell(index);
        this.cellIndex = index;
        //宽度
        if(width > 0){
            setColumnWidth(width);
        }
        //设置图片
        addImage(url);
    }

    public ZlCell(XSSFWorkbook wb,ZlSheet sheet,ZlRow row,Integer index,Object content){
        this(wb,sheet,row,index,content,false,0,(short)11);
    }

    public ZlCell(XSSFWorkbook wb,ZlSheet sheet,ZlRow row,Integer index,Object content,boolean hold){
        this(wb,sheet,row,index,content,hold,0,(short)11);
    }


    public ZlCell(XSSFWorkbook wb,ZlSheet sheet,ZlRow row,Integer index,Object content,boolean hold,int width){
        this(wb,sheet,row,index,content,hold,width,(short)11);
    }


    public ZlCell(XSSFWorkbook wb,ZlSheet sheet,ZlRow row,Integer index,Object content,boolean hold,short fontSize){
        this(wb,sheet,row,index,content,hold,0,fontSize);
    }

    public ZlCell(XSSFWorkbook wb,ZlSheet sheet,ZlRow row,Integer index,Object content,boolean hold,int width,short fontSize){
        this.wb = wb;
        this.sheet = sheet;
        this.row = row;
        this.cell = row.getRow().createCell(index);
        this.cellIndex = index;
        this.style = wb.createCellStyle();
        this.font = wb.createFont();
        //默认宋体
        this.font.setFontName("宋体");
        this.font.setBold(hold);
        this.font.setFontHeightInPoints(fontSize);

        this.style.setFont(font);
        //默认横 纵向居中
        this.style.setAlignment(HorizontalAlignment.CENTER);
        this.style.setVerticalAlignment(VerticalAlignment.CENTER);
        //默认添加边线
        this.style.setBorderTop(BorderStyle.THIN);
        this.style.setBorderBottom(BorderStyle.THIN);
        this.style.setBorderLeft(BorderStyle.THIN);
        this.style.setBorderRight(BorderStyle.THIN);
        this.cell.setCellStyle(style);
        this.cellNo = UUID.randomUUID().toString();
        setCellValue(content);
        //宽度
        if(width > 0){
            setColumnWidth(width);
        }
    }

    public void setContent(Object content) {
        this.content = content;
        setCellValue(content);
    }

    private void setCellValue(Object content){
        this.content = content;
        if(content instanceof  Number){
            this.cell.setCellValue(((Number) content).doubleValue());
        }else if(content instanceof String){
            this.cell.setCellValue((String) content);
        }else if(content instanceof Date){
            this.cell.setCellValue((Date) content);
        }else if(content instanceof Boolean){
            this.cell.setCellValue((Boolean) content);
        }else{
            this.cell.setCellValue(String.valueOf(content));
        }
    }


    /**
     * 设置字体类型 如宋体
     */
    public ZlCell setFontName(String font){
        this.font.setFontName(font);
        return this;
    }

    /**
     * 设置是否为粗体
     */
    public ZlCell setFontBold(boolean bold){
        this.font.setBold(bold);
        return this;
    }

    /**
     * 设置字体高度
     */
    public ZlCell setFontHeight(short height){
        this.font.setFontHeightInPoints(height);
        return this;
    }

    /**
     * 设置横向内容方向
     */
    public ZlCell setHorizontalAlignment(HorizontalAlignment alignment){
        this.style.setAlignment(alignment);
        this.cell.setCellStyle(style);
        return this;
    }

    /**
     * 设置纵向内容方向
     */
    public ZlCell setVerticalAlignment(HorizontalAlignment alignment){
        this.style.setAlignment(alignment);
        this.cell.setCellStyle(style);
        return this;
    }

    /**
     * 上边线
     */
    public ZlCell setBorderTop(BorderStyle borderStyle){
        this.style.setBorderTop(borderStyle);
        this.cell.setCellStyle(style);
        return this;
    }

    /**
     * 下边线
     */
    public ZlCell setBorderBottom(BorderStyle borderStyle){
        this.style.setBorderBottom(borderStyle);
        this.cell.setCellStyle(style);
        return this;
    }

    /**
     * 左边线
     */
    public ZlCell setBorderLeft(BorderStyle borderStyle){
        this.style.setBorderLeft(borderStyle);
        this.cell.setCellStyle(style);
        return this;
    }

    /**
     * 右边线
     */
    public ZlCell setBorderRight(BorderStyle borderStyle){
        this.style.setBorderRight(borderStyle);
        this.cell.setCellStyle(style);
        return this;
    }

    public ZlCell mergeCell(int firstRow, int firstCell, String endRowNo, String endCellNo){
        List<ZlRow> rows =  this.sheet.getRows();
        ZlRow endRow = rows.stream().filter(r->r.getRowNo().equalsIgnoreCase(endRowNo)).findFirst().orElse(null);
        if(endRow == null){
            return this;
        }
        ZlCell endCell = endRow.getCells().stream().filter(c->c.getCellNo().equalsIgnoreCase(endCellNo)).findFirst().orElse(null);
        if(endCell == null){
            return this;
        }
        if(firstRow == endRow.getRowIndex()){
            //如果是同行的列合并
            for(int i = firstCell ; i<= endCell.getCellIndex() ; i++){
                for(ZlCell cell : endRow.getCells()){
                    if(cell.getCellIndex() == i){
                        cell.setCellNo(this.cellNo);
                    }
                }
            }
        }
        endCell.setCellNo(this.cellNo);
        CellRangeAddress region = new CellRangeAddress(firstRow, endRow.getRowIndex(), firstCell, endCell.getCellIndex());
        this.sheet.getSheet().addMergedRegion(region);
        return this;
    }

    public ZlCell mergeCell(String endRowNo,String endCellNo){
        int firstRow = this.row.getRowIndex();
        int firstCell = this.getCellIndex();
        return mergeCell(firstRow,firstCell,endRowNo,endCellNo);
    }

    public ZlCell mergeCell(Integer endRowIndex,Integer endCellIndex){
        int firstRow = this.row.getRowIndex();
        int firstCell = this.getCellIndex();
        for (int i = 0; i < sheet.getSheet().getNumMergedRegions(); i++) {
            CellRangeAddress mergedRegion = sheet.getSheet().getMergedRegion(i);
            if (mergedRegion.getFirstColumn() == firstCell &&
                    mergedRegion.getLastColumn() == endCellIndex &&
                    (mergedRegion.getFirstRow() >= firstRow ||
                            mergedRegion.getLastRow() <= endRowIndex)) {
                // 如果找到了包含该行的合并区域，则移除它
                sheet.getSheet().removeMergedRegion(i);
            }
        }
        System.out.println();
        CellRangeAddress region = new CellRangeAddress(firstRow, endRowIndex, firstCell, endCellIndex);
        this.sheet.getSheet().addMergedRegion(region);
        return this;
    }

    public ZlCell setColumnWidth(int width){
        this.sheet.getSheet().setColumnWidth(this.cell.getColumnIndex(),width * 256);
        return this;
    }


    public String getCellNo() {
        return cellNo;
    }

    public void setCellNo(String cellNo) {
        this.cellNo = cellNo;
    }

    public int getCellIndex() {
        return cellIndex;
    }

    public void setCellIndex(int cellIndex) {
        this.cellIndex = cellIndex;
    }

    public Object getContent() {
        return content;
    }

    public ZlCell setBackground(IndexedColors background) {
        this.background = background;
        for(ZlCell cell :this.row.getCells()){
            if(cell.getCellNo().equalsIgnoreCase(this.cellNo)){
                cell.getCell().getCellStyle().setFillBackgroundColor(background.getIndex());
            }
        }

        return this;
    }

    public ZlCell setFontColor(IndexedColors fontColor) {
        this.fontColor = fontColor;
        this.font.setColor(fontColor.getIndex());
        this.cell.getCellStyle().setFont(this.font);
        return this;
    }

    public Cell getCell() {
        return cell;
    }


    public ZlCell addImage(String filePath){
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            File file = new File(filePath);
            BufferedImage bufferImg = ImageIO.read(file);
            String imageType = filePath.substring(filePath.length()-3);
            ImageIO.write(bufferImg, imageType, outputStream);
            XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0,
                    this.cellIndex, this.row.getRowIndex(),  this.cellIndex+1, this.row.getRowIndex() +1);
            anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
            //插入图片
            this.sheet.getPatriarch().createPicture(anchor, wb.addPicture(outputStream.toByteArray(), XSSFWorkbook.PICTURE_TYPE_JPEG));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return this;
    }


    private ByteArrayOutputStream inputToOutput(InputStream inputStream){
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            byte[] buffer = new byte[1024];

            int len;
            while ((len = inputStream.read(buffer)) > -1) {
                baos.write(buffer, 0, len);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return baos;
    }
}
